<body>
<p>Provides support for the encoding of objects, and the objects reachable from them,
   into <code>XML</code>; and the complementary reconstruction of the
   object graph from <code>XML</code>. 
</p>

<h2><a name="OVERVIEW">XML marshalling/unmarshalling facility:</a></h2>


<IMG alt="XML Data Binding" src="doc-files/xmlDataBinding.png">

<p> Key Advantages:<ul>
    <li> Real-time characteristics with no adverse effect on memory footprint or 
         garbage collection (e.g. it can be used for time critical communications).
         {@link javolution.xml.XMLFormat XMLFormat} is basically a "smart" 
         wrapper around our real-time StAX-like
         {@link javolution.xml.stream.XMLStreamReader XMLStreamReader} and 
         {@link javolution.xml.stream.XMLStreamWriter XMLStreamWriter}.</li>
    <li> Works directly with your existing Java classes, no need to create new classes
         or customize your implementation in any way.</li>
    <li> The XML representation can be high level and impervious to obfuscation
         or changes to your implementation.</li>
    <li> Performance on a par or better than default Java<sup>TM</sup> Serialization/Deserialization 
         (See <a href="https://bindmark.dev.java.net/">bindmark</a> for performance comparison).</li>
    <li> Runs on any platform including J2ME CLDC 1.0 It does not require reflection or 
         or any interface (e.g. <code>Serializable</code>) to be implemented.</li>
    <li> The XML mapping can be defined for a top class (or interface) and is automatically 
         inherited by all sub-classes (or all implementing classes).</li>
    <li> Supports object references (to avoid expanding objects already formatted).</li>
    </ul>
</p>

<p> The default XML mapping for a class and its sub-classes is typically defined using 
    a <code>static final</code> {@link javolution.xml.XMLFormat XMLFormat} instance. 
    For example:[code]
      public abstract class Graphic implements XMLSerializable {
          private boolean _isVisible;
          private Paint _paint; // null if none.
          private Stroke _stroke; // null if none.
          private Transform _transform; // null if none.
           
          // Default XML format with name associations (members identified by an unique name).
          // See XMLFormat for examples of positional associations.
          protected static final XMLFormat<Graphic> XML = new XMLFormat<Graphic>(Graphic.class) {
               public void write(Graphic g, OutputElement xml) throws XMLStreamException {
                   xml.setAttribute("isVisible", g._isVisible); 
                   xml.add(g._paint, "Paint");
                   xml.add(g._stroke, "Stroke");
                   xml.add(g._transform, "Transform");
               }
               public void read(InputElement xml, Graphic g) throws XMLStreamException {
                   g._isVisible = xml.getAttribute("isVisible", true);
                   g._paint = xml.get("Paint");
                   g._stroke = xml.get("Stroke");
                   g._transform = xml.get("Transform");
              }
          };
      }[/code]
    Sub-classes may override the inherited XML format:[code]
      public class Area extends Graphic {
          private Shape _geometry;  
        
          // Adds geometry to format.
          protected static final XMLFormat<Area> XML = new XMLFormat<Area>(Area.class) {
              public void write(Area area, OutputElement xml) throws XMLStreamException {
                  Graphic.XML.write(area, xml); // Calls parent write.
                  xml.add(area._geometry, "Geometry");
              }
              public void read(InputElement xml, Area area) throws XMLStreamException {
                  Graphic.XML.read(xml, area); // Calls parent read.
                  area._geometry = xml.get("Geometry");
              }
          };
      }[/code]
    
    The following writes a graphic area to a file, then reads it:[code]
    
      // Creates some useful aliases for class names.
      XMLBinding binding = new XMLBinding();
      binding.setAlias(Color.class, "Color");
      binding.setAlias(Polygon.class, "Polygon");
      binding.setClassAttribute("type"); // Use "type" instead of "class" for class attribute.
    
      // Writes the area to a file.
      XMLObjectWriter writer = XMLObjectWriter.newInstance(new FileOutputStream("C:/area.xml"));
      writer.setBinding(binding); // Optional.
      writer.setIndentation("\t"); // Optional (use tabulation for indentation).
      writer.write(area, "Area", Area.class);
      writer.close(); 

      // Reads the area back
      XMLObjectReader reader = XMLObjectReader.newInstance(new FileInputStream("C:/area.xml"));
      reader.setBinding(binding);
      Area a = reader.read("Area", Area.class);
      reader.close();
      [/code]
 
    Here is an example of valid XML representation for an area:[code]
      <Area isVisible="true">
          <Paint type="Color" rgb="#F3EBC6" />
          <Geometry type="Polygon">
              <Vertex x="123" y="-34" />
              <Vertex x="-43" y="-34" />
              <Vertex x="-12" y="123" />
          </Geometry>
      </Area>[/code]
   
</p>
<p> The following table illustrates the variety of XML representations supported 
    (Foo class with a single String member named text):
    <center>
      <table cellpadding="2" cellspacing="2" border="1" style="text-align: left"><tbody>
      <tr>
        <td style="vertical-align: top; text-align: center;"><span style="font-weight: bold;">XML FORMAT</span></td>
        <td style="vertical-align: top; text-align: center;"><span style="font-weight: bold;">XML DATA</span></td>
      </tr>
      <tr>
<td>[code]XMLFormat<Foo> XML = new XMLFormat<Foo>(Foo.class) {
    public void write(Foo foo, OutputElement xml) throws XMLStreamException {
        xml.setAttribute("text", foo.text); 
    }
    public void read(InputElement xml, Foo foo) throws XMLStreamException {
        foo.text = xml.getAttribute("text", "");
    }
};[/code]</td>
<td><pre>
 <b>&lt;!-- Member as attribute --&gt;</b>
 &lt;Foo text="This is a text"/&gt;
</pre></td>
      </tr>
      
      <tr>
<td>[code]XMLFormat<Foo> XML = new XMLFormat<Foo>(Foo.class) {
    public void write(Foo foo, OutputElement xml) throws XMLStreamException {
        xml.add(foo.text); 
    }
    public void read(InputElement xml, Foo foo) throws XMLStreamException {
        foo.text = xml.getNext();
    }
};[/code]</td>
<td><pre>
 <b>&lt;!-- Member as anonymous nested element --&gt;</b>
 &lt;Foo&gt;
     &lt;java.lang.String value="This is a text"/&gt;
 &lt;/Foo&gt;
</pre></td>
      </tr>

      <tr>
<td>[code]XMLFormat<Foo> XML = new XMLFormat<Foo>(Foo.class) {
    public void write(Foo foo, OutputElement xml) throws XMLStreamException {
        xml.addText(foo.text);
        // or xml.getStreamWriter().writeCDATA(foo.text) to use CDATA block. 
    }
    public void read(InputElement xml, Foo foo) throws XMLStreamException {
        foo.text = xml.getText().toString(); // Content of a text-only element.
    }
};[/code]</td>
<td><pre>
 <b>&lt;!-- Member as Character Data --&gt;</b>
 &lt;Foo&gt;This is a text&lt;/Foo&gt;
</pre></td>
      </tr>

      <tr>
<td>[code]XMLFormat<Foo> XML = new XMLFormat<Foo>(Foo.class) {
    public void write(Foo foo, OutputElement xml) throws XMLStreamException {
        xml.add(foo.text, "Text"); 
    }
    public void read(InputElement xml, Foo foo) throws XMLStreamException {
        foo.text = xml.get("Text");
    }
};[/code]</td>
<td><pre>
 <b>&lt;!-- Member as named element of unknown type  --&gt;</b>
 &lt;Foo&gt;
     &lt;Text class="java.lang.String" value="This is a text"/&gt;
 &lt;/Foo&gt;
</pre></td>
      </tr>

      <tr>
<td>[code]XMLFormat<Foo> XML = new XMLFormat<Foo>(Foo.class) {
    public void write(Foo foo, OutputElement xml) throws XMLStreamException {
        xml.add(foo.text, "Text", String.class); 
    }
    public void read(InputElement xml, Foo foo) throws XMLStreamException {
        foo.text = xml.get("Text", String.class);
    }
};[/code]</td>
<td><pre>
 <b>&lt;!-- Member as named element of actual type known --&gt;</b>
 &lt;Foo&gt;
     &lt;Text value="This is a text"/&gt;
 &lt;/Foo&gt;
</pre></td>
      </tr>
      </tbody></table>
    </center>
</p>

<p> The {@link javolution.xml.XMLFormat XMLFormat} does not have to use the class
    public no-arg constructor, instances can be created using factory methods, 
    private constructors (with constructor parameters set from the XML element) or even retrieved from a collection 
    (if the object is shared or unique). For example:[code]
        public final class Point implements XMLSerializable { 
            // Default XMLFormat can be private as the class cannot be extended.
            static final XMLFormat<Point> XML = new XMLFormat<Point>(Point.class) {
                public boolean isReferencable() {
                    return false; // Always manipulates by value.
                }
                public Point newInstance(Class<Point> cls, InputElement xml) throws XMLStreamException {
                    return Point.valueOf(xml.getAttribute("x", 0), xml.getAttribute("y", 0)); 
                }
                public void write(Point point, OutputElement xml) throws XMLStreamException {
                    xml.setAttribute("x", point._x);
                    xml.setAttribute("y", point._y);
                }
                public void read(InputElement xml, Point point) throws XMLStreamException {
                    // Do nothing immutable.
                }
            };
            private int _x;
            private int _y;
            private Point() {}; // No-arg constructor not visible.
            public static Point valueOf(int x, int y) { ... }
        }[/code]
</p>

<p> Document cross-references are supported, including circular references. 
    Let's take for example:[code]
        public class Polygon implements Shape, XMLSerializable { 
            private Point[] _vertices;
            static final XMLFormat<Polygon> XML = new XMLFormat<Polygon>(Polygon.class) {
                public void write(Polygon polygon, OutputElement xml) throws XMLStreamException {
                    xml.setAttibutes("count", _vertices.length);
                    for (int i=0; i < _vertices.length; i++) {
                        xml.add(_vertices[i], "Vertex", Point.class);
                    }
                }
                public void read(InputElement xml, Polygon polygon) throws XMLStreamException {
                    int count = xml.getAttributes("count", 0);
                    polygon._vertices = new Point[count];
                    for (int i=0; i < count; i++) {
                        _vertices[i] = xml.get("Vertex", Point.class);
                    }
                }
            };
        }
        Polygon[] polygons = new Polygon[] {p1, p2, p1};
        ...
        TextBuilder xml = TextBuilder.newInstance();
        AppendableWriter out = new AppendableWriter().setOutput(xml)
        XMLObjectWriter writer = XMLObjectWriter.newInstance(out);
        writer.setXMLReferenceResolver(new XMLReferenceResolver()); // Enables cross-references.
        writer.write(polygons, "Polygons", Polygon[].class); 
        writer.close();
        System.out.println(xml);
        [/code]
    Prints the following (noticed that the first polygon and last one are being shared).[code]
      <Polygons length="3">
          <Polygon id="0" count="3">
              <Vertex x="123" y="-34" />  
              <Vertex x="-43" y="-34" />
              <Vertex x="-12" y="123" />
          </Polygon>
          <Polygon id="1" count="3">
              <Vertex x="-43" y="-34" />
              <Vertex x="123" y="-34" />
              <Vertex x="-12" y="123" />
          </Polygon>
          <Polygon ref="0"/>
      </Polygons>[/code] 
</p>

<B>ALGORITHMS:</B>

<p> Our {@link javolution.xml.XMLObjectReader XMLObjectReader}/{@link javolution.xml.XMLObjectWriter XMLObjectWriter} 
    are in fact simple wrappers around our <b>J</b>avolution high-performance StAX-like
    {@link javolution.xml.stream.XMLStreamReader XMLStreamReader} and 
    {@link javolution.xml.stream.XMLStreamWriter XMLStreamWriter} classes. 
    The logic of these wrappers is described below:
<pre>

OutputElement.add(object, name, uri, class):

1. if (object == null) return

2. getStreamWriter().writeStartElement(uri, name)

3. isReference = referenceResolver.writeReference(object, this)
   
4. if (!isReference) binding.getFormat(class).write(object, this)

5. getStreamWriter().writeEndElement()

6. end


InputElement.get(name, uri, class):

1. if (!getStreamReader().getLocalName().equals(name) ||
        !getStreamReader().getNamespaceURI().equals(uri)) return null
        
2. object = referenceResolver.readReference(inputElement)
   
3. if (object != null) Goto 8 // Found reference

4. format = binding.getFormat(class)

5. object = format.newInstance(class, inputElement)

6. referenceResolver.createReference(object, inputElement) // Done before parsing to support circular references.

7. format.read(inputElement, object)

8. getStreamReader().nextTag()

9. end
</pre></p>
</body>